﻿using Microsoft.Extensions.Logging;
using Simple.Tools;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.Framework.Logger
 * 接口名称 ClassNameLogger
 * 开发人员：zdm
 * 创建时间：2023/11/28 9:51:06
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.Framework.Logger
{
	internal class ClassNameLogger<T> : ClassNameLogger,Microsoft.Extensions.Logging.ILogger<T>
	{

		public ClassNameLogger(string name, string folderPath,string profixLogName,eRollingInterval rollingInterval,bool IsConsoleWrite) :base(name, folderPath, profixLogName,rollingInterval,IsConsoleWrite)
		{
		}

		public IDisposable BeginScope<TState>(TState state)
		{
			return base.BeginScope(state); // 如果需要支持作用域，请返回一个实现了IDisposable接口的对象
		}

		public bool IsEnabled(LogLevel logLevel)
		{
			return base.IsEnabled(logLevel); // 指定日志级别，这里设置为所有级别都输出日志
		}

		public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
		{
			base.Log<TState>(logLevel, eventId, state, exception, formatter);
		}

	}


	internal class ClassNameLogger : Microsoft.Extensions.Logging.ILogger
	{
		/// <summary>
		/// 类名称
		/// </summary>
		protected readonly string className;
		/// <summary>
		/// 文件夹
		/// </summary>
		protected readonly string logFolderPath;
		/// <summary>
		/// 前缀
		/// </summary>
		protected readonly string profixLogName;

		protected readonly eRollingInterval rollingInterval;

		protected  string logFileName;
		protected  bool isConsoleWrite;
		/// <summary>
		/// 记录日志等级
		/// </summary>

		protected  LogLevel currentLeve;

	  
		public ClassNameLogger(string name, string folderPath, string profixLogName, eRollingInterval rollingInterval,bool IsConsoleWrite)
		{
			this.className = name;
			this.logFolderPath = folderPath;
			this.profixLogName = profixLogName;
			this.rollingInterval = rollingInterval;
			this.isConsoleWrite = IsConsoleWrite;
	
		}

		public IDisposable BeginScope<TState>(TState state)
		{
			return null; // 如果需要支持作用域，请返回一个实现了IDisposable接口的对象
		}

		public bool IsEnabled(LogLevel logLevel)
		{
			currentLeve=logLevel;
			return true; // 指定日志级别，这里设置为所有级别都输出日志
		}
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TState"></typeparam>
		/// <param name="logLevel"></param>
		/// <param name="eventId"></param>
		/// <param name="state"></param>
		/// <param name="exception"></param>
		/// <param name="formatter"></param>
		public void Log<TState>(LogLevel logLevel, EventId eventId,TState state, Exception exception,Func<TState, Exception, string> formatter)
		{
			if (!ToolSimpleCheck.IsNullOrEmpty(profixLogName))
			{
				logFileName = $"{profixLogName}_{DateToString(rollingInterval)}";
			}
			else
			{
				logFileName = DateToString(rollingInterval);
			}
			logFilePath = System.IO.Path.Combine(logFolderPath,logFileName);
			ToolSimpleCheck.CreateFile(logFilePath);

			if ((int)logLevel>=(int)currentLeve)
			{
				// 根据类名创建日志文件名
				
				ToolSimpleCheck.CreateFile(logFilePath);
				try
				{
					string message = null;
					if (logLevel==LogLevel.Error||logLevel==LogLevel.Trace||logLevel==LogLevel.Debug)
					{
						message = $"DATE\t{DateTime.Now}\t{logLevel} \t\t {className}\t{formatter(state, exception)}";
					}
					else
					{
						message = $"DATE\t{DateTime.Now}\t{logLevel} \t {className}\t{formatter(state, exception)}";
					}
					if (isConsoleWrite)
					{
						ConsoleWrite(logLevel, message);
					}
					messages.Add(message);
					//PeekMessage();
				}
				catch (Exception ex)
				{
					ConsoleWrite(LogLevel.Error,ex.Message);
					ConsoleWrite(LogLevel.Error,ex.StackTrace);

				
				}
			}
		}
		public void ConsoleWrite(LogLevel logLevel, string message)
		{

			ConsoleColor currentForeColor = Console.ForegroundColor;
			//Console.OutputEncoding= Encoding.UTF8;
			//				Console.WriteLine($"DATE:{DateTime.Now};{context}");
			//				Console.ForegroundColor = currentForeColor;
			switch (logLevel)
			{
				case LogLevel.Trace:
				case LogLevel.Debug:
				case LogLevel.Information:
					Console.ForegroundColor = ConsoleColor.White;
					break;
				case LogLevel.Warning:
					Console.ForegroundColor = ConsoleColor.DarkYellow;
					break;
				case LogLevel.Error:
					Console.ForegroundColor = ConsoleColor.DarkRed;
					break;
				case LogLevel.Critical:
					break;
				case LogLevel.None:
					break;
				default:
					break;
			}
			Console.WriteLine(message);
			Console.ForegroundColor = ConsoleColor.White;
		}

		private string DateToString(eRollingInterval eRollingInterval)
		{
			string dataString = string.Empty;
			switch (eRollingInterval)
			{
				case eRollingInterval.Infinite:
					break;
				case eRollingInterval.Year:
					dataString = $"{DateTime.Now.ToString("yyyy")}.log";
					break;
				case eRollingInterval.Month:
					dataString = $"{DateTime.Now.ToString("yyyyMM")}.log";
					break;
				case eRollingInterval.Day:
					dataString = $"{DateTime.Now.ToString("yyyy_MM_dd")}.log";
					break;
				case eRollingInterval.Hour:
					dataString = $"{DateTime.Now.ToString("yyyy_MM_dd_hh")}.log";
					break;
				case eRollingInterval.Minute:
					dataString = $"{DateTime.Now.ToString("yyyyMMdd_hh_mm")}.log";
					break;
				default:
					break;
			}

			return dataString;
		}

		static ClassNameLogger()
		{
			messages = new BlockingCollection<string>(1000);
			WriteLogger();
		}
		/// <summary>
		/// 
		/// </summary>
		public static string logFilePath;
		private static BlockingCollection<string> messages;
		private static void WriteLogger()
		{
			Task.Run(() =>
			{
				while (true)
				{
					while (messages!=null&& messages.Count() > 0)
					{
						try
						{
							string message = messages.Take();
							if (ToolSimpleCheck.IsNullOrEmpty(message))
							{
								System.IO.File.AppendAllText(logFilePath, message + "\n");
							}
						}
						catch (Exception ex)
						{
							if (ex.Message.Contains("because it is being used by another process!"))
							{
								break;
							}
						}
					}
					Task.Delay(3000).Wait();
				};
			});
		}
		

	}
}
